/**
 * @file bl0939.h
 * @brief bl0939(2路交流电能计量芯片)驱动
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2020-10-21
 * @copyright Copyright (c) 2020  烽火通信
 */
#ifndef __BL0939_H
#define __BL0939_H 
#include "project_config.h"

#if DRV_BL0939_EN
#include "bl0939_config.h"
#include "bsp_uart_v2.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"

/* 电参量寄存器（只读） */
#define Addr_IA_FAST_RMS     0x00       ///< A 通道快速有效值，无符号
#define Addr_IA_WAVE         0x01       ///< A 通道电流波形寄存器，有符号
#define Addr_IB_WAVE         0x02       ///< B 通道电流波形寄存器，有符号
#define Addr_V_WAVE          0x03       ///< 电压波形寄存器，有符号
#define Addr_IA_RMS          0x04       ///< A 通道电流有效值寄存器，无符号
#define Addr_IB_RMS          0x05       ///< B 通道电流有效值寄存器，无符号
#define Addr_V_RMS           0x06       ///< 电压有效值寄存器，无符号
#define Addr_IB_FAST_RMS     0x07       ///< B 通道快速有效值，无符号
#define Addr_A_WATT          0x08       ///< A 通道有功寄存器，有符号
#define Addr_B_WATT          0x09       ///< B 通道有功寄存器，有符号
#define Addr_CFA_CNT         0x0A       ///< A 通道有功电能脉冲计数，无符号
#define Addr_CFB_CNT         0x0B       ///< B 通道有功电能脉冲计数，无符号
#define Addr_A_CORNER        0x0C       ///< A 通道电流电压波形相角寄存器
#define Addr_B_CORNER        0x0D       ///< B 通道电流电压波形相角寄存器
#define Addr_TPS1            0x0E       ///< 内部温度检测寄存器，无符号
#define Addr_TPS2            0x0F       ///< 外部温度检测寄存器，无符号

/* 用户操作寄存器（读写） */
#define Addr_IA_FAST_RMS_CTRL    0x10   ///< A 通道快速有效值控制寄存器
#define Addr_IA_CHOS         0x11       ///< 电流 A 通道直流偏置校正
#define Addr_IB_CHOS         0x12       ///< 电流 B 通道直流偏置校正
#define Addr_IA_RMSOS        0x13       ///< 电流 A 通道有效值小信号校正寄存器
#define Addr_IB_RMSOS        0x14       ///< 电流 B 通道有效值小信号校正寄存器
#define Addr_A_WATTOS        0x15       ///< A 通道功率小信号校正寄存器
#define Addr_B_WATTOS        0x16       ///< B 通道功率小信号校正寄存器
#define Addr_WA_CREEP        0x17       ///< 有功功率防潜寄存器
#define Addr_USR_MODE        0x18       ///< 用户模式选择寄存器
#define Addr_SOFT_RESET      0x19       ///< 写入 0x5A5A5A 时，用户区寄存器复位
#define Addr_USR_WRPROT      0x1A       ///< 用户写保护设置寄存器。写入 0x55 时，表示可操作用户寄存器
#define Addr_TPS_CTRL        0x1B       ///< 温度模式控制寄存器
#define Addr_TPS2_A          0x1C       ///< 外部温度传感器增益系数校正寄存器
#define Addr_TPS2_B          0x1D       ///< 外部温度传感器偏移系数校正寄存器
#define Addr_IB_FAST_RMS_CTRL    0x1E   ///< B 通道快速有效值控制寄存器



/* 电参数读取选项，可多项或组合 */
#define BL0939_ELECT_P_A    0x01
#define BL0939_ELECT_P_B    0x02
#define BL0939_ELECT_I_A    0x04
#define BL0939_ELECT_I_B    0x08
#define BL0939_ELECT_V      0x10
#define BL0939_ELECT_L_A    0x20
#define BL0939_ELECT_L_B    0x40
#define BL0939_ELECT_TPS    0x80

#define BL0939_ELECT_P_ALL  0x03
#define BL0939_ELECT_I_ALL  0x0C
#define BL0939_ELECT_ALL    0xFF

#ifndef BL0939_ENERGY_PERIOD
#define BL0939_ENERGY_PERIOD    60000
#endif


/**
 * @brief BL0939的电参数定义
 */
typedef struct Bl0939_Elect_s
{
#if BL0939_ELECT_USE_FLOAT
#if BL0939_A_WATT_EN
    float Power_Value_A;        ///< 通道A有功功率 unit: W
#endif
#if BL0939_B_WATT_EN
    float Power_Value_B;        ///< 通道B有功功率 unit: W
#endif
#if BL0939_IA_RMS_EN
    float Current_Value_A;      ///< 通道A有效电流 uint: A
#endif
#if BL0939_IB_RMS_EN
    float Current_Value_B;      ///< 通道B有效电流 uint: A
#endif
#if BL0939_V_RMS_EN
    float Voltage_Value;        ///< 有效电压 uint: V
#endif
#if BL0939_IA_FAST_RMS_EN
    float LeakCur_Value_A;      ///< 通道A漏电流 uint: A
#endif
#if BL0939_IB_FAST_RMS_EN
    float LeakCur_Value_B;      ///< 通道B漏电流 uint: A
#endif
#if BL0939_TPS1_EN
    float TPS1;                 ///< unit: ℃
#endif

#else
#if BL0939_A_WATT_EN
    uint32_t Power_Value_A;     ///< 通道A有功功率 unit: 0.1W
#endif
#if BL0939_B_WATT_EN
    uint32_t Power_Value_B;     ///< 通道B有功功率 unit: 0.1W
#endif
#if BL0939_IA_RMS_EN
    uint32_t Current_Value_A;   ///< 通道A有效电流 uint: 0.001A
#endif
#if BL0939_IB_RMS_EN
    uint32_t Current_Value_B;   ///< 通道B有效电流 uint: 0.001A
#endif
#if BL0939_V_RMS_EN
    uint32_t Voltage_Value;     ///< 有效电压 uint: 0.1V
#endif
#if BL0939_IA_FAST_RMS_EN
    uint32_t LeakCur_Value_A;   ///< 通道A漏电流 uint: 0.001A
#endif
#if BL0939_IB_FAST_RMS_EN
    uint32_t LeakCur_Value_B;   ///< 通道B漏电流 uint: 0.001A
#endif
#if BL0939_TPS1_EN
    int16_t TPS1;               ///< unit: 0.1℃
#endif
#endif
} Bl0939_Elect_t;

/** @brief 统计电量结构体 */
typedef struct Bl0939_Energy_s
{
#if BL0939_ENERGY_USE_FLOAT
#if BL0939_CFA_EN
    float Energy_A;             ///< A通道电量统计 uint: 千瓦小时
#endif
#if BL0939_CFB_EN
    float Energy_B;             ///< B通道电量统计 uint: 千瓦小时
#endif
#else
#if BL0939_CFA_EN
    uint32_t Energy_A;          ///< A通道电量统计 uint: 0.001千瓦小时
#endif
#if BL0939_CFB_EN
    uint32_t Energy_B;          ///< B通道电量统计 uint: 0.001千瓦小时
#endif
#endif
} Bl0939_Energy_t;

#if !(BL0939_ENERGY_USE_FLOAT && BL0939_CF_CLR_SEL)
/** @brief 统计电量清零保存结构体 */
typedef struct Bl0939_EnergyMid_s
{
#if BL0939_ENERGY_USE_FLOAT
#if BL0939_CFA_EN
    float EnergyMid_A;          ///< A通道清零保存 uint: 千瓦小时
#endif
#if BL0939_CFB_EN
    float EnergyMid_B;          ///< B通道清零保存 uint: 0.001千瓦小时
#endif
#else
#if BL0939_CFA_EN
    uint32_t EnergyMid_A;       ///< A通道电量寄存器余数
#endif
#if BL0939_CFB_EN
    uint32_t EnergyMid_B;       ///< B通道电量寄存器余数
#endif
#endif
} Bl0939_EnergyMid_t;
#endif

/**
 * @brief BL0939对象结构体
 */
typedef struct Bl0939_s
{
    UartId_t UartId;        ///< 使用的串口编号
    // Gpio_t CF;           ///< A 通道漏电/过流报警输出指示引脚
    bool IsInitialized;     ///< 是否初始化
    uint8_t Addr;           ///< 协议地址

#if BL0939_ELECT_USE_FLOAT
    float Voltage_K;        ///< 电压转换系数
    float Current_K;        ///< 电流转换系数
    float L_Current_K;
    float Power_K;          ///< 有功功率转换系数
#else
    uint32_t Voltage_K;     ///< 电压转换系数
    uint32_t Current_K;     ///< 电流转换系数
    uint32_t L_Current_K;
    uint32_t Power_K;       ///< 有功功率转换系数
#endif

#if BL0939_ENERGY_USE_FLOAT
    float Energy_K;         ///< 电能脉冲计数，对应于1度电的脉冲计数
#else
    uint32_t Energy_K;      ///< 电能脉冲计数，对应于1度电的脉冲计数
#endif

    Bl0939_Energy_t Energy;         ///< 实际用电量
#if !(BL0939_ENERGY_USE_FLOAT && BL0939_CF_CLR_SEL)
    Bl0939_EnergyMid_t EnergyMid;   ///< 电量清零保存值
#endif

    TimerHandle_t bl_timer;         ///< 电量统计计时器
    SemaphoreHandle_t WR_lock;      ///< 通信锁
    SemaphoreHandle_t Energy_lock;  ///< 电量读写锁

    uint8_t resume_times;   ///< 自恢复次数
} Bl0939_t;

/**
 * @brief Bl0939初始化
 * @param[in]  obj      Bl0939对象
 * @param[in]  uartId   串口外设编号
 * @param[in]  tx       串口TX引脚
 * @param[in]  rx       串口RX引脚
 * @param[in]  cf       CF引脚
 * @param[in]  addr     器件地址
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_ALREADY_INIT - 已初始化
 * - @ref BSP_ERROR - 初始化出错
 * - @ref BSP_ERROR_NO_MEM - 内存出错
 */
int8_t Bl0939_Init( Bl0939_t *obj, UartId_t uartId, PinNames tx, PinNames rx, PinNames cf, uint8_t addr );

/**
 * @brief Bl0939去初始化
 * @param[in]  obj      Bl0939对象
 */
void Bl0939_DeInit( Bl0939_t *obj );

/**
 * @brief Bl0939设置电量值
 * @param[in]  obj      Bl0939对象
 * @param[in]  Energy   设置的电量信息结构体
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_NO_INIT - 未初始化
 */
int8_t Bl0939_SetEnergy( Bl0939_t *obj, Bl0939_Energy_t *Energy );

/**
 * @brief Bl0939获取电量值
 * @param[in]  obj      Bl0939对象
 * @param[in]  Energy   统计的电量信息结构体
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_NO_INIT - 未初始化
 */
int8_t Bl0939_GetEnergy( Bl0939_t *obj, Bl0939_Energy_t *Energy );

/**
 * @brief 获取电量瞬时参数
 * @param[in]  obj      Bl0939对象
 * @param[in]  Elect    电参数信息
 * @param[in]  mask     电参数选项掩码
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref ERROR_INVALID_PARAM - 非法入参
 * @par 示例:
 * @code
 *    Bl0939_GetElect( obj, Elect, BL0939_ELECT_P_ALL );
 *    Bl0939_GetElect( obj, Elect, BL0939_ELECT_I_A | BL0939_ELECT_L_B );
 * @endcode
 */
int8_t Bl0939_GetElect( Bl0939_t *obj, Bl0939_Elect_t *Elect, uint8_t mask );

#endif  /* BL0939_EN */

#endif	 // __BL0939_H 

/*********** (C) COPYRIGHT 2020 FiberHome *****END OF FILE****/
